package cn.iocoder.yudao.module.erp.service.stock;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRejectReqVO;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.bpm.service.task.BpmTasktooServiceImpl;
import cn.iocoder.yudao.module.erp.common.InventoryTurnover;
import cn.iocoder.yudao.module.erp.controller.admin.checkout.vo.CheckOutRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.pristock.vo.PriStockSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSaveReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.priaccount.PriAccountDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.pristock.PriStockDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.secaccount.SecAccountDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.secstock.SecStockDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehouseinlist.WarehouseInListDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehouseoutlist.WarehouseOutListDO;
import cn.iocoder.yudao.module.erp.dal.mysql.priaccount.PriAccountMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.pristock.PriStockMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.secaccount.SecAccountMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.secstock.SecStockMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockCheckItemMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockCheckMapper;
import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO;
import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum;
import cn.iocoder.yudao.module.erp.service.pristock.PriStockService;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.erp.service.secstock.SecStockService;
import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;

// TODO 芋艿：记录操作日志

/**
 * ERP 库存盘点单 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class ErpStockCheckServiceImpl implements ErpStockCheckService {

    @Resource
    private ErpStockCheckMapper stockCheckMapper;
    @Resource
    private ErpStockCheckItemMapper stockCheckItemMapper;
    @Resource
    private DeptMapper deptMapper;
    @Resource
    private AdminUserMapper adminUserMapper;
    @Resource
    private ErpNoRedisDAO noRedisDAO;
    @Resource
    private SecAccountMapper secAccountMapper;
    @Resource
    private PriAccountMapper priAccountMapper;
    @Resource
    private BpmProcessInstanceApi bpmProcessInstanceApi;
    @Resource
    private BpmTasktooServiceImpl bpmTasktooService;
    @Resource
    private BpmProcessInstanceService processInstanceService;
    @Resource
    private ErpStockRecordService stockRecordService;
    @Resource
    private PriStockService priStockService;
    @Resource
    private PriStockMapper priStockMapper;
    @Resource
    private SecStockMapper secStockMapper;
    @Resource
    private SecStockService secStockService;
    @Resource
    private InventoryTurnover inventoryTurnover;

    @Value("department_stockcheck")
    private String PROCESS_KEY2;
    @Value("warehouse_stockcheck")
    private String PROCESS_KEY;

    @Value("${erp.departments.taskname}")
    private String TASK_NAME2;
    @Value("${erp.warehouse.taskname}")
    private String TASK_NAME1;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createStockCheck(ErpStockCheckSaveReqVO createReqVO) {
        // 1.1 校验盘点项的有效性
        List<ErpStockCheckItemDO> stockCheckItems = createReqVO.getItems();
        // 1.2 生成盘点单号，并校验唯一性
        String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_CHECK_NO_PREFIX);
        if (stockCheckMapper.selectByNo(no) != null) {
            throw exception(STOCK_CHECK_NO_EXISTS);
        }
        // 2.1 插入盘点单
        ErpStockCheckDO stockCheck = BeanUtils.toBean(createReqVO, ErpStockCheckDO.class, in -> in
                .setNo(no).setStatus(0).setDeptId(createReqVO.getDeptId()).setCreateTime(createReqVO.getCreateTime())
                .setTotalCount(getSumValue(createReqVO.getItems(), ErpStockCheckItemDO::getRowcount, BigDecimal::add)));
        stockCheckMapper.insert(stockCheck);
        stockCheckItems.forEach(o -> o.setCheckId(stockCheck.getId()));
        stockCheckItemMapper.insertBatch(stockCheckItems);
        return                                                                                                                                                    createReqVO.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStockCheck(ErpStockCheckSaveReqVO updateReqVO) {
        // 1.1 校验存在
        ErpStockCheckDO stockCheck = validateStockCheckExists(updateReqVO.getId());
        if (ErpAuditStatus.APPROVE.getStatus().equals(stockCheck.getStatus())) {
            throw exception(STOCK_CHECK_UPDATE_FAIL_APPROVE, stockCheck.getNo());
        }
        // 1.2 校验盘点项的有效性
        List<ErpStockCheckItemDO> stockCheckItems = updateReqVO.getItems();

        // 2.1 更新盘点单
        ErpStockCheckDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockCheckDO.class, in -> in
                .setTotalCount(getSumValue(stockCheckItems, ErpStockCheckItemDO::getRowcount, BigDecimal::add))
                .setTotalPrice(getSumValue(stockCheckItems, ErpStockCheckItemDO::getTotalPrice, BigDecimal::add)));
        stockCheckMapper.updateById(updateObj);
        // 2.2 更新盘点单项
        updateStockCheckItemList(updateReqVO.getId(), stockCheckItems);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStockCheckStatus(Long id, Integer status, String taskId) {
        boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status);
        // 1.1 校验存在
        ErpStockCheckDO stockCheck = validateStockCheckExists(id);
        // 1.2 校验状态
        if (stockCheck.getStatus().equals(status)) {
            throw exception(approve ? STOCK_CHECK_APPROVE_FAIL : STOCK_CHECK_PROCESS_FAIL);
        }
        // 2. 更新状态
        int updateCount = stockCheckMapper.updateByIdAndStatus(id, stockCheck.getStatus(),
                new ErpStockCheckDO().setStatus(status));
        if (updateCount == 0) {
            throw exception(approve ? STOCK_CHECK_APPROVE_FAIL : STOCK_CHECK_PROCESS_FAIL);
        }
        Integer warehouseLevel = stockCheck.getWarehouseLevel();
        if (status == 1){
            if (warehouseLevel == 1) {
//        发起BPM流程
            HashMap<String, Object> processInstanceVariables = new HashMap<>();
            String processInstanceId = bpmProcessInstanceApi.createProcessInstance(getLoginUserId(),
                    new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
                            .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(stockCheck.getId()))
                            .setStartUserSelectAssignees(null));//        将工作流的编号，更新到核销报废管理单中
            stockCheck.setProcessInstanceId(processInstanceId);
            stockCheckMapper.updateProcessInstanceIdById(processInstanceId,id);
            }else if (warehouseLevel == 2) {
                //        发起BPM流程
                HashMap<String, Object> processInstanceVariables = new HashMap<>();
                String processInstanceId = bpmProcessInstanceApi.createProcessInstance(getLoginUserId(),
                        new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY2)
                                .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(stockCheck.getId()))
                                .setStartUserSelectAssignees(null));
//        将工作流的编号，更新到核销报废管理单中
                stockCheck.setProcessInstanceId(processInstanceId);
                stockCheckMapper.updateProcessInstanceIdById(processInstanceId,id);
            }

        }

    }

    private List<ErpStockCheckItemDO> validateStockCheckItems(List<ErpStockCheckItemDO> list) {
//         1.1 校验产品存在
//        List<PriStockDO> productList =
//        Map<Long, PriStockDO> productMap = convertMap(productList, PriStockDO::getId);
        // 1.2 校验仓库存在
//        warehouseService.validWarehouseList(convertSet(list, ErpStockCheckSaveReqVO.Item::getDeptId));
//         2. 转化为 ErpStockCheckItemDO 列表
        return list;
//
    }

    private void updateStockCheckItemList(Long id, List<ErpStockCheckItemDO> newList) {
        // 第一步，对比新老数据，获得添加、修改、删除的列表
        List<ErpStockCheckItemDO> oldList = stockCheckItemMapper.selectListByCheckId(id);
        List<List<ErpStockCheckItemDO>> diffList = diffList(oldList, newList, // id 不同，就认为是不同的记录
                (oldVal, newVal) -> oldVal.getId().equals(newVal.getId()));

        // 第二步，批量添加、修改、删除
        if (CollUtil.isNotEmpty(diffList.get(0))) {
            diffList.get(0).forEach(o -> o.setCheckId(id));
            stockCheckItemMapper.insertBatch(diffList.get(0));
        }
        if (CollUtil.isNotEmpty(diffList.get(1))) {
            stockCheckItemMapper.updateBatch(diffList.get(1));
        }
        if (CollUtil.isNotEmpty(diffList.get(2))) {
            stockCheckItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockCheckItemDO::getId));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteStockCheck(List<Long> ids) {
        // 1. 校验不处于已审批
        List<ErpStockCheckDO> stockChecks = stockCheckMapper.selectBatchIds(ids);
        if (CollUtil.isEmpty(stockChecks)) {
            return;
        }
        stockChecks.forEach(stockCheck -> {
            if (ErpAuditStatus.APPROVE.getStatus().equals(stockCheck.getStatus())) {
                throw exception(STOCK_CHECK_DELETE_FAIL_APPROVE, stockCheck.getNo());
            }
        });

        // 2. 遍历删除，并记录操作日志
        stockChecks.forEach(stockCheck -> {
            // 2.1 删除盘点单
            stockCheckMapper.deleteById(stockCheck.getId());
            // 2.2 删除盘点单项
            stockCheckItemMapper.deleteByCheckId(stockCheck.getId());
        });
    }

    private ErpStockCheckDO validateStockCheckExists(Long id) {
        ErpStockCheckDO stockCheck = stockCheckMapper.selectById(id);
        if (stockCheck == null) {
            throw exception(STOCK_CHECK_NOT_EXISTS);
        }
        return stockCheck;
    }

    @Override
    public ErpStockCheckRespVO getStockCheck(Long id) {
        ErpStockCheckDO erpStockCheckDO = stockCheckMapper.selectById(id);
        ErpStockCheckRespVO erpStockCheckRespVO = BeanUtils.toBean(erpStockCheckDO, ErpStockCheckRespVO.class);
        erpStockCheckRespVO.setCreatorName(adminUserMapper.selectById(erpStockCheckDO.getCreator()).getNickname());
        erpStockCheckRespVO.setDeptName(deptMapper.selectById(erpStockCheckDO.getDeptId()).getName());
        return erpStockCheckRespVO;
    }

    @Override
    public PageResult<ErpStockCheckRespVO> getStockCheckPage(ErpStockCheckPageReqVO pageReqVO) {
        PageResult<ErpStockCheckDO> erpStockCheckDOPageResult = stockCheckMapper.selectPage(pageReqVO);
        PageResult<ErpStockCheckRespVO> erpStockCheckRespVOPageResult = BeanUtils.toBean(erpStockCheckDOPageResult, ErpStockCheckRespVO.class);
        Set<Long> deptIds = new HashSet<>();
        Set<Long> creatorIds = new HashSet<>();
        // 1. 收集所有需要查询的部门ID
        for (ErpStockCheckRespVO erpStockCheckRespVO : erpStockCheckRespVOPageResult.getList()) {
            deptIds.add(erpStockCheckRespVO.getDeptId());
            creatorIds.add(erpStockCheckRespVO.getCreator());
        }
        // 2. 使用这些ID一次性查询部门信息
        Map<Long, String> deptNameMap = new HashMap<>();
        if (CollUtil.isNotEmpty(deptIds)) {
            List<DeptDO> deptList = deptMapper.selectBatchIds(deptIds);
            for (DeptDO deptDO : deptList) {
                deptNameMap.put(deptDO.getId(), deptDO.getName());
            }
        }
        // 3. 使用这些ID一次性查询用户信息
        Map<Long, String> creatorUsernameMap = new HashMap<>();
        if (CollUtil.isNotEmpty(creatorIds)) {
            List<AdminUserDO> userList = adminUserMapper.selectByIds(creatorIds);
            for (AdminUserDO adminUserDO : userList) {
                creatorUsernameMap.put(adminUserDO.getId(), adminUserDO.getNickname());
            }
        }
        // 4. 在循环中从Map中获取部门名称
        for (ErpStockCheckRespVO erpStockCheckRespVO : erpStockCheckRespVOPageResult.getList()) {
            erpStockCheckRespVO.setDeptName(deptNameMap.get(erpStockCheckRespVO.getDeptId()));
            erpStockCheckRespVO.setCreatorName(creatorUsernameMap.get(erpStockCheckRespVO.getCreator()));
        }
        return erpStockCheckRespVOPageResult;
    }

    // ==================== 盘点项 ====================

    @Override
    public List<ErpStockCheckItemDO> getStockCheckItemListByCheckId(Long checkId) {
        return stockCheckItemMapper.selectListByCheckId(checkId);
    }

    @Override
    public List<ErpStockCheckItemDO> getStockCheckItemListByCheckIds(Collection<Long> checkIds) {
        if (CollUtil.isEmpty(checkIds)) {
            return Collections.emptyList();
        }
        return stockCheckItemMapper.selectListByCheckIds(checkIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteStockCheck(Long id) {
        // 校验存在
        validateStockCheckExists(id);
        // 删除
        stockCheckMapper.deleteById(id);

        // 删除子表
        deleteStockCheckItemByCheckId(id);
    }

    @Override
    public void deleteStockCheckItem(Long id) {
        // 校验存在
        validateStockCheckItemExists(id);
        // 删除
        stockCheckItemMapper.deleteById(id);
    }

    @Override
    public PageResult<ErpStockCheckRespVO> getStockCheckPageByStatus(ErpStockCheckPageReqVO pageReqVO) {
        List<Task> taskTodoPage;
        taskTodoPage = bpmTasktooService.getTaskTodoToo(getLoginUserId(),TASK_NAME2 );
        taskTodoPage.addAll(bpmTasktooService.getTaskTodoToo(getLoginUserId(),TASK_NAME1 ));
        List<String> processInstanceIds = taskTodoPage.stream().map(Task::getProcessInstanceId).collect(Collectors.toList());
        pageReqVO.setProcessInstanceIds(processInstanceIds);
        PageResult<ErpStockCheckDO> erpStockCheckDOPageResult = stockCheckMapper.selectPageByStatus(pageReqVO);
        PageResult<ErpStockCheckRespVO> erpStockCheckRespVOPageResult = BeanUtils.toBean(erpStockCheckDOPageResult, ErpStockCheckRespVO.class);
        Set<Long> deptIds = new HashSet<>();
        Set<Long> creatorIds = new HashSet<>();
        // 1. 收集所有需要查询的部门ID
        for (ErpStockCheckRespVO erpStockCheckRespVO : erpStockCheckRespVOPageResult.getList()) {
            deptIds.add(erpStockCheckRespVO.getDeptId());
            creatorIds.add(erpStockCheckRespVO.getCreator());
        }
        // 2. 使用这些ID一次性查询部门信息
        Map<Long, String> deptNameMap = new HashMap<>();
        if (CollUtil.isNotEmpty(deptIds)) {
            List<DeptDO> deptList = deptMapper.selectBatchIds(deptIds);
            for (DeptDO deptDO : deptList) {
                deptNameMap.put(deptDO.getId(), deptDO.getName());
            }
        }
        // 3. 使用这些ID一次性查询用户信息
        Map<Long, String> creatorUsernameMap = new HashMap<>();
        if (CollUtil.isNotEmpty(creatorIds)) {
            List<AdminUserDO> userList = adminUserMapper.selectByIds(creatorIds);
            for (AdminUserDO adminUserDO : userList) {
                creatorUsernameMap.put(adminUserDO.getId(), adminUserDO.getNickname());
            }
        }
        // 4. 在循环中从Map中获取部门名称
        for (ErpStockCheckRespVO erpStockCheckRespVO : erpStockCheckRespVOPageResult.getList()) {
            erpStockCheckRespVO.setDeptName(deptNameMap.get(erpStockCheckRespVO.getDeptId()));
            erpStockCheckRespVO.setCreatorName(creatorUsernameMap.get(erpStockCheckRespVO.getCreator()));
        }
        //        把taskTodoPage集合中的taskId设置到checkOutRespVO中
        for (ErpStockCheckRespVO erpStockCheckRespVO : erpStockCheckRespVOPageResult.getList()) {
            for (Task processInstanceId : taskTodoPage) {
                if (erpStockCheckRespVO.getProcessInstanceId().equals(processInstanceId.getProcessInstanceId())) {
                    erpStockCheckRespVO.setTaskId(processInstanceId.getId());
                }
            }
        }
        return erpStockCheckRespVOPageResult;
    }

    @Override
    public void approveStockCheck(Long id, BpmTaskApproveReqVO reqVO) {
        // 校验存在
        ErpStockCheckDO stockCheck = validateStockCheckExists(id);
        // 通过工作流
        bpmTasktooService.approveTaskToo(getLoginUserId(), reqVO);
        ProcessInstance processInstance = processInstanceService.getProcessInstance(stockCheck.getProcessInstanceId());
        // 判断工作流是否为最终通过
        if (processInstance == null) {
//            HistoricProcessInstance historicProcessInstance = processInstanceService.getHistoricProcessInstance(stockCheck.getProcessInstanceId());
//            Integer processInstanceStatus = FlowableUtils.getProcessInstanceStatus(historicProcessInstance);
            stockCheckMapper.updateById(stockCheck.setStatus(3).setRemark(reqVO.getReason()));
            Integer warehouseLevel = stockCheck.getWarehouseLevel();
            List<ErpStockCheckItemDO> stockCheckItems = stockCheckItemMapper.selectListByCheckId(id);
            if (warehouseLevel == 1) {
                List<PriStockDO> priStockDOList = updatePriStockCount(stockCheckItems);
                createPriInventoryTurnoverList(priStockDOList);
            }else if (warehouseLevel == 2) {
                List<SecStockDO> secStockDOS = updateSecStockCount(stockCheckItems);
                createSecInventoryTurnoverList(secStockDOS);
            }
        }else {
            Integer processInstanceStatus = FlowableUtils.getProcessInstanceStatus(processInstance);
            // 2. 更新状态
            stockCheckMapper.updateById(stockCheck.setStatus(processInstanceStatus).setRemark(reqVO.getReason()));
        }

    }

    // 更新二级库库存
    private List<SecStockDO> updateSecStockCount(List<ErpStockCheckItemDO> stockCheckItems){
        List<SecStockDO> stocksToUpdate = new ArrayList<>();
        // 批量获取库存记录
        List<SecStockDO> productsByBatch = secStockService.selectStockListByProductBatch(stockCheckItems.stream()
                .map(item -> new SecStockDO(item.getProductId(), item.getProductBatch(),item.getDeptId()))
                .collect(Collectors.toList()));
        // 用于存储分组结果的 Map
        Map<String, List<SecStockDO>> groupedMap = new HashMap<>();
        // 遍历集合
        for (SecStockDO stockDO : productsByBatch) {
            // 拼接键
            String key = stockDO.getProductId() + stockDO.getProductBatch();
            // 获取当前键对应的列表，如果不存在则创建一个新列表
            List<SecStockDO> list = groupedMap.computeIfAbsent(key, k -> new ArrayList<>());
            // 将当前对象添加到列表中
            list.add(stockDO);
        }
        // 准备更新数据
        for (ErpStockCheckItemDO item : stockCheckItems) {
            // 获取变更数量
            BigDecimal rowcount = item.getRowcount();
            if (rowcount.compareTo(BigDecimal.ZERO) < 0) {
                String mapKey = item.getProductId() + item.getProductBatch(); // 拼接键
                for (SecStockDO secStockDO : groupedMap.get(mapKey)) {
                    BigDecimal count = secStockDO.getCount();
                    // 判断当前批次数量是否足够
                    if (count.compareTo(rowcount.abs()) >= 0) {
                        secStockDO.setCount(rowcount);
                        stocksToUpdate.add(secStockDO);
                        break;
                    } else if (count.compareTo(rowcount.abs()) < 0) {
                        secStockDO.setCount(count.negate());
                        stocksToUpdate.add(secStockDO);
                        rowcount = rowcount.add(count);
                    }
                }
            } else if (rowcount.compareTo(BigDecimal.ZERO) > 0) {
                String mapKey = item.getProductId() + item.getProductBatch(); // 拼接键
                List<SecStockDO> list = groupedMap.get(mapKey); // 获取当前键对应的列表
                if (list != null) {
                    SecStockDO last = list.get(list.size() - 1); // 获取最后一个元素
                    last.setCount(rowcount);
                    stocksToUpdate.add(last);
                }
            }
        }
        secStockService.updateSecStockCountBatch(stocksToUpdate);
        return stocksToUpdate;
    }

    private void createSecInventoryTurnoverList(List<SecStockDO> stocksToUpdate){
        Boolean inFlag = false; // 入库标志
        Boolean outFlag = false; // 出库标志
        WarehouseInListDO warehouseInListDO = new WarehouseInListDO();
        WarehouseOutListDO warehouseOutListDO = new WarehouseOutListDO();
        String deptId = "";
        for (SecStockDO secStockDO : stocksToUpdate) {
            BigDecimal count = secStockDO.getCount();
            deptId = String.valueOf(secStockDO.getDeptId());
            if (count.compareTo(BigDecimal.ZERO) > 0) {
                inFlag = true;
            }else if (count.compareTo(BigDecimal.ZERO) < 0){
                outFlag = true;
            }
            if (inFlag && outFlag) {
                break;
            }
        }
        String inId = "";
        String outId = "";
        // 插入
        if (inFlag) {
            inId = inventoryTurnover.creatWarehouseInList(warehouseInListDO.setInDeptId(deptId).setOutDeptId(deptId));
        }
        if (outFlag) {
            outId = inventoryTurnover.creatWarehouseOutList(warehouseOutListDO.setInDeptId(deptId).setOutDeptId(deptId));
        }
        // 更新二级库台账
        updateSecRecords(stocksToUpdate,inId,outId);
    }

    // 更新二级库台账
    private void updateSecRecords(List<SecStockDO> stocksToUpdate,String inId, String outId){
        List<SecAccountDO> accountRecords = new ArrayList<>();
        for (SecStockDO secStockDO : stocksToUpdate) {
            SecAccountDO secAccountDO = new SecAccountDO();
            BigDecimal count = secStockDO.getCount();
            Long deptId = secStockDO.getDeptId();
            String affairs = "盘点溢出";
            if (count.compareTo(BigDecimal.ZERO) == 0) {
                continue;
            }
            if (count.compareTo(BigDecimal.ZERO) < 0) {
                affairs = "盘点缺失";
                secAccountDO.setAffairsId(outId);
            }else {
                secAccountDO.setAffairsId(inId);
            }
//                处理插入二级库台账的数据
            BeanUtils.copyProperties(secStockDO, secAccountDO);
            secAccountDO.setDeptId(deptId).setFromDeptId(deptId).setToDeptId(deptId)
                    .setAffairs(affairs)
                    .setStatus(1) // 使用常量或枚举
                    .setId(null).setCreateTime(LocalDateTime.now())
                    .setUpdateTime(null);
            accountRecords.add(secAccountDO);
        }
        // 批量插入二级库台账记录
        if (!accountRecords.isEmpty()) {
            boolean insertResult = secAccountMapper.insertBatch(accountRecords);
            if (!insertResult) {
                throw new RuntimeException("台账记录插入失败");
            }
        }
    }

    // 更新一级库库存
    private List<PriStockDO> updatePriStockCount(List<ErpStockCheckItemDO> stockCheckItems){
        List<PriStockDO> stocksToUpdate = new ArrayList<>();
        // 批量获取库存记录
        List<PriStockDO> productsByBatch = priStockService.selectStockListByProductBatch(stockCheckItems.stream()
                .map(item -> new PriStockDO(item.getProductId(), item.getProductBatch(),item.getDeptId()))
                .collect(Collectors.toList()));
        // 用于存储分组结果的 Map
        Map<String, List<PriStockDO>> groupedMap = new HashMap<>();
        // 遍历集合
        for (PriStockDO stockDO : productsByBatch) {
            // 拼接键
            String key = stockDO.getProductId() + stockDO.getProductBatch();
            // 获取当前键对应的列表，如果不存在则创建一个新列表
            List<PriStockDO> list = groupedMap.computeIfAbsent(key, k -> new ArrayList<>());
            // 将当前对象添加到列表中
            list.add(stockDO);
        }
        // 准备更新数据
        for (ErpStockCheckItemDO item : stockCheckItems) {
            // 获取变更数量
            BigDecimal rowcount = item.getRowcount();
            if (rowcount.compareTo(BigDecimal.ZERO) < 0) {
                String mapKey = item.getProductId() + item.getProductBatch(); // 拼接键
                for (PriStockDO priStockDO : groupedMap.get(mapKey)) {
                    BigDecimal count = priStockDO.getCount();
                    // 判断当前批次数量是否足够
                    if (count.compareTo(rowcount.abs()) >= 0) {
                        priStockDO.setCount(rowcount);
                        stocksToUpdate.add(priStockDO);
                        break;
                    } else if (count.compareTo(rowcount.abs()) < 0) {
                        priStockDO.setCount(count.negate());
                        stocksToUpdate.add(priStockDO);
                        rowcount = rowcount.add(count);
                    }
                }
            } else if (rowcount.compareTo(BigDecimal.ZERO) > 0) {
                String mapKey = item.getProductId() + item.getProductBatch(); // 拼接键
                List<PriStockDO> list = groupedMap.get(mapKey); // 获取当前键对应的列表
                if (list != null) {
                    PriStockDO last = list.get(list.size() - 1); // 获取最后一个元素
                    last.setCount(rowcount);
                    stocksToUpdate.add(last);
                }
            }
        }
        priStockService.updatePristockCountBatch(stocksToUpdate);
        return stocksToUpdate;
    }

    private void createPriInventoryTurnoverList(List<PriStockDO> stocksToUpdate){
        Boolean inFlag = false; // 入库标志
        Boolean outFlag = false; // 出库标志
        WarehouseInListDO warehouseInListDO = new WarehouseInListDO();
        WarehouseOutListDO warehouseOutListDO = new WarehouseOutListDO();
        String deptId = "";
        for (PriStockDO priStockDO : stocksToUpdate) {
            BigDecimal count = priStockDO.getCount();
            deptId = String.valueOf(priStockDO.getDeptId());
            if (count.compareTo(BigDecimal.ZERO) > 0) {
                inFlag = true;
            }else if (count.compareTo(BigDecimal.ZERO) < 0){
                outFlag = true;
            }
            if (inFlag && outFlag) {
                break;
            }
        }
        // 批量插入
        String inId = "";
        String outId = "";
        // 插入
        if (inFlag) {
            inId = inventoryTurnover.creatWarehouseInList(warehouseInListDO.setInDeptId(deptId).setOutDeptId(deptId));
        }
        if (outFlag) {
            outId = inventoryTurnover.creatWarehouseOutList(warehouseOutListDO.setInDeptId(deptId).setOutDeptId(deptId));
        }
        // 更新二级库台账
        updatePriRecords(stocksToUpdate,inId,outId);
    }

    //
    private void updatePriRecords(List<PriStockDO> stocksToUpdate, String inId, String outId){
        List<PriAccountDO> accountRecords = new ArrayList<>();
        for (PriStockDO priStockDO : stocksToUpdate){
            PriAccountDO priAccountDO = new PriAccountDO();
            BigDecimal count = priStockDO.getCount();
            Long deptId = priStockDO.getDeptId();
            String affairs = "盘点溢出";
            if (count.compareTo(BigDecimal.ZERO) == 0) {
                continue;
            }
            if (count.compareTo(BigDecimal.ZERO) < 0) {
                affairs = "盘点缺失";
                priAccountDO.setAffairsId(outId);
            }else {
                priAccountDO.setAffairsId(inId);
            }
//                处理插入二级库台账的数据
            BeanUtils.copyProperties(priStockDO, priAccountDO);
            priAccountDO.setDeptId(deptId).setFromDeptId(deptId).setToDeptId(deptId)
                    .setAffairs(affairs)
                    .setStatus(1L) // 使用常量或枚举
                    .setId(null).setCreateTime(LocalDateTime.now())
                    .setUpdateTime(null);
            accountRecords.add(priAccountDO);
        }
        // 批量插入一级库台账记录
        if (!accountRecords.isEmpty()) {
            boolean insertResult = priAccountMapper.insertBatch(accountRecords);
            if (!insertResult) {
                throw new RuntimeException("台账记录插入失败");
            }
        }
    }

    @Override
    public void rejectStockCheck(Long id, BpmTaskRejectReqVO reqVO) {
        ErpStockCheckDO stockCheck = validateStockCheckExists(id);
        bpmTasktooService.rejectTaskToo(getLoginUserId(), reqVO);
        ProcessInstance processInstance = processInstanceService.getProcessInstance(stockCheck.getProcessInstanceId());
        if (processInstance == null) {
//            HistoricProcessInstance historicProcessInstance = processInstanceService.getHistoricProcessInstance(stockCheck.getProcessInstanceId());
//            Integer processInstanceStatus = FlowableUtils.getProcessInstanceStatus(historicProcessInstance);
            stockCheckMapper.updateById(stockCheck.setStatus(2).setRemark(reqVO.getReason()));
        }else {
            // 2. 更新状态
            Integer processInstanceStatus = FlowableUtils.getProcessInstanceStatus(processInstance);
            stockCheckMapper.updateById(stockCheck.setStatus(processInstanceStatus).setRemark(reqVO.getReason()));
        }
    }

    private void validateStockCheckItemExists(Long id) {
        if (stockCheckItemMapper.selectById(id) == null) {
            throw exception(STOCK_CHECK_ITEM_NOT_EXISTS);
        }
    }

    private void deleteStockCheckItemByCheckId(Long checkId) {
        stockCheckItemMapper.deleteByCheckId(checkId);
    }

}